// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.

using Stride.Core;
using Stride.Core.Serialization;
using Stride.Core.Serialization.Contents;
using Stride.Engine.Design;
using Stride.Core.Mathematics;

namespace Stride.BepuPhysics.Definitions
{
    /// <summary>
    /// A collection of convex hulls decomposed from an input model
    /// </summary>
    [DataContract]
    [ContentSerializer(typeof(DataContentSerializer<DecomposedHulls>))]
    [DataSerializerGlobal(typeof(CloneSerializer<DecomposedHulls>), Profile = "Clone")]
    [ReferenceSerializer, DataSerializerGlobal(typeof(ReferenceSerializer<DecomposedHulls>), Profile = "Content")]
    public class DecomposedHulls
    {
        /// <summary>
        /// Convex hulls for each meshes the decomposed model contained
        /// </summary>
        public ReadOnlySpan<DecomposedMesh> Meshes => InternalMeshes;

        /// <summary> Only for serialization purposes, components using this class do not expect writes after init </summary>
        [DataMember]
        internal DecomposedMesh[] InternalMeshes { get; init; } = [];

        public DecomposedHulls() { }

        /// <summary>
        /// This method expects full ownership over this array
        /// </summary>
        public DecomposedHulls(DecomposedMesh[] meshes)
        {
            InternalMeshes = meshes;
        }

        [DataContract]
        public class DecomposedMesh
        {
            /// <summary>
            /// The hulls generated by decomposing this mesh
            /// </summary>
            public ReadOnlySpan<Hull> Hulls => InternalHulls;

            /// <summary> Only for serialization purposes, components using this class do not expect writes after init </summary>
            [DataMember]
            internal Hull[] InternalHulls { get; init; } = [];

            public DecomposedMesh() { }

            /// <summary>
            /// This method expects full ownership over this array
            /// </summary>
            public DecomposedMesh(Hull[] hulls)
            {
                InternalHulls = hulls;
            }
        }

        [DataContract]
        public class Hull
        {
            /// <summary>
            /// The points marking the bounds of the hull
            /// </summary>
            public ReadOnlySpan<Vector3> Points => InternalPoints;

            /// <summary>
            /// Indices used to recreate a 3d mesh from those points
            /// </summary>
            public ReadOnlySpan<uint> Indices => InternalIndices;

            /// <summary> Only for serialization purposes, components using this class do not expect writes after init </summary>
            [DataMember]
            internal Vector3[] InternalPoints { get; init; } = [];

            /// <summary> Only for serialization purposes, components using this class do not expect writes after init </summary>
            [DataMember]
            internal uint[] InternalIndices { get; init; } = [];

            public Hull() { }

            /// <summary>
            /// This method expects full ownership over those arrays
            /// </summary>
            public Hull(Vector3[] points, uint[] indices)
            {
                InternalPoints = points;
                InternalIndices = indices;
            }
        }
    }
}
